#include "PixelsFollowMouse.h"

PixelsFollowMouse::PixelsFollowMouse(void)
{
	/* Initialize the SDL library */
    if (SDL_Init(SDL_INIT_VIDEO) < 0)
	{
        cerr << "Couldn't initialize SDL: %s\n" << SDL_GetError() << endl;
    }

	const int WINDOW_WIDTH = 320;
	const int WINDOW_HEIGHT = 240;
	const char* WINDOW_TITLE = "Sample Pixels following Mouse";

	/*
     * Initialize the display in a 640x480 8-bit palettized mode,
     * requesting a software surface
     */
    screen = SDL_SetVideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, 0, SDL_HWSURFACE | SDL_DOUBLEBUF);
    if (screen == NULL)
	{
        cerr << "Couldn't set 320x240x8 video mode: %s\n" << SDL_GetError() << endl;
    }
	else
	{
		SDL_WM_SetCaption(WINDOW_TITLE, 0);
	}
}

PixelsFollowMouse::~PixelsFollowMouse(void)
{
	SDL_FreeSurface(screen);
	SDL_Quit();
}

void PixelsFollowMouse::run(void)
{
	bool quit = false;
	SDL_Event event;
	Uint32 yellow = SDL_MapRGB(screen->format, 0xff, 0xff, 0x00);
	while (!quit)
	{
		while (SDL_PollEvent(&event))
		{
			switch (event.type)
			{
				case SDL_MOUSEMOTION:
					{
						SDL_LockSurface(screen);
						putPixel(event.motion.x, event.motion.y, yellow);
						SDL_UnlockSurface(screen);
						SDL_UpdateRect(screen, 0, 0, 0, 0);
					}
					break;
				case SDL_KEYDOWN:
					{
						if (event.key.keysym.sym == SDLK_ESCAPE)
						{
							quit = true;
						}
					}
				case SDL_QUIT:
					quit = true;
					break;
			}
		}
		SDL_PumpEvents();
	}
}

/*
 * Set the pixel at (x, y) to the given value
 * NOTE: The surface must be locked before calling this!
 */
void PixelsFollowMouse::putPixel(int x, int y, Uint32 pixel)
{
    int bpp = screen->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to set */
    Uint8 *p = (Uint8*)screen->pixels + y * screen->pitch + x * bpp;

    switch(bpp)
	{
	case 1:
        *p = pixel;
        break;
    case 2:
        *(Uint16*)p = pixel;
        break;

    case 3:
        if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
		{
            p[0] = (pixel >> 16) & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = pixel & 0xff;
        }
		else
		{
            p[0] = pixel & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = (pixel >> 16) & 0xff;
        }
        break;
    case 4:
        *(Uint32*)p = pixel;
        break;
    }
}
